import { ThrottleUtilParamFun, ThrottleUtilReturn } from '../types'

export type ThrottleByTimeOptionsType = {
  interval?: number
  thisArg?: any
}

/**
 * 根据调用函数的时间间隔对函数进行节流处理，当目前调用函数的时间距离上次函数调用时间的间隔小
 * 于指定间隔，则不执行函数的调用，直到函数调用的时间与上次函数调用时间的间隔大于或等于指定间
 * 隔时，才执行函数的调用。
 *
 * @param {ThrottleUtilParamFun} fun 要进行节流处理的函数
 * @param {ThrottleByTimeOptionsType} options 配置选项
 * - interval 相邻两次函数调用的时间间隔，单位为 ms，默认为 500ms
 * - thisArg 指定需要节流处理的函数(传统函数)调用时的 this 指向，默认为 null，即非严格模
 * 式下函数调用时的 this 指向全局对象，严格模式下为 thisArg 指定的值；对于需要节流处理的函
 * 数为箭头函数时，该参数无效，箭头函数的 this 指向由函数定义时确定，不受 thisArg 参数影响，
 * 箭头函数的 this 来源于箭头函数定义时的上级作用域。
 * @returns {ThrottleUtilReturn} 节流处理后的函数
 */
export const throttleByTime = (
  fun: ThrottleUtilParamFun,
  options?: ThrottleByTimeOptionsType
): ThrottleUtilReturn => {
  const { interval, thisArg } = {
    interval: 500,
    thisArg: null,
    ...options
  }
  // 记录上次函数调用时间
  let lastTime = 0
  return async (...args: any[]): Promise<void | any> => {
    // 获取当前调用函数时的时间
    const now = Date.now()
    // 如果距离上次函数调用时间间隔小于指定间隔，则不执行函数
    if (now - lastTime < interval) return
    // 更新上次函数调用时间
    lastTime = now
    // 调用函数，并返回函数调用结果
    return await fun.apply(thisArg, args)
  }
}

export type ThrottleByTimeType = typeof throttleByTime
